package com.demo.connectdbtest.module.minio.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.demo.connectdbtest.config.MinIOConfigProperties;
import com.demo.connectdbtest.module.minio.service.FileStorageService;
import io.minio.GetObjectArgs;
import io.minio.ListObjectsArgs;
import io.minio.MinioClient;
import io.minio.PutObjectArgs;
import io.minio.RemoveObjectArgs;
import io.minio.Result;
import io.minio.errors.ErrorResponseException;
import io.minio.errors.InsufficientDataException;
import io.minio.errors.InternalException;
import io.minio.errors.InvalidResponseException;
import io.minio.errors.ServerException;
import io.minio.errors.XmlParserException;
import io.minio.messages.Item;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

@Slf4j
@Service
public class MinIOFileStorageService implements FileStorageService {
    @Autowired
    private MinioClient minioClient;

    @Autowired
    private MinIOConfigProperties minIOConfigProperties;

    private final static String separator = "/"; //文件夹分隔符

    /**
     * 构建文件的绝对路径
     *
     * @param dirPath  文件路径
     * @param filename 文件名  yyyy/mm/dd/file.jpg
     * @return /test
     */
    public String builderFilePath(String dirPath, String filename) {
        StringBuilder stringBuilder = new StringBuilder(50);
        if (!StringUtils.isEmpty(dirPath)) {
            stringBuilder.append(dirPath).append(separator);
        }
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
        String todayStr = sdf.format(new Date());
        stringBuilder.append(todayStr).append(separator);
        stringBuilder.append(filename);
        return stringBuilder.toString();
    }

    /**
     * 上传图片文件
     *
     * @param prefix      文件前缀
     * @param filename    文件名
     * @param inputStream 文件流
     * @return 文件全路径
     */
    @Override
    public String uploadImgFile(String prefix, String filename, InputStream inputStream) {
        String filePath = builderFilePath(prefix, filename);
        try {
            PutObjectArgs putObjectArgs = PutObjectArgs.builder()
                    .object(filePath)
                    .contentType("image/jpg")
                    .bucket(minIOConfigProperties.getBucket()).stream(inputStream, inputStream.available(), -1)
                    .build();
            minioClient.putObject(putObjectArgs);
            StringBuilder urlPath = new StringBuilder(minIOConfigProperties.getReadPath());
            urlPath.append(separator + minIOConfigProperties.getBucket());
            urlPath.append(separator);
            urlPath.append(filePath);
            return urlPath.toString();
        } catch (Exception ex) {
            log.error("minio put file error.", ex);
            throw new RuntimeException("上传文件失败");
        }
    }

    /**
     * 上传html文件
     *
     * @param prefix      文件前缀
     * @param filename    文件名
     * @param inputStream 文件流
     * @return 文件全路径
     */
    @Override
    public String uploadHtmlFile(String prefix, String filename, InputStream inputStream) {
        String filePath = builderFilePath(prefix, filename);
        try {
            PutObjectArgs putObjectArgs = PutObjectArgs.builder()
                    .object(filePath) //文件名
                    .contentType("text/html")//文件类型
                    .bucket(minIOConfigProperties.getBucket())//桶名称与minio创建的桶一致
                    .stream(inputStream, inputStream.available(), -1)//文件流
                    .build();
            minioClient.putObject(putObjectArgs);
            StringBuilder urlPath = new StringBuilder(minIOConfigProperties.getReadPath());
            urlPath.append(separator + minIOConfigProperties.getBucket());
            urlPath.append(separator);
            urlPath.append(filePath);
            return urlPath.toString(); //文件全路径
        } catch (Exception ex) {
            log.error("minio put file error.", ex);
            ex.printStackTrace();
            throw new RuntimeException("上传文件失败");
        }
    }

    /**
     * 删除文件
     *
     * @param pathUrl 文件全路径
     */
    @Override
    public void delete(String pathUrl) {
        String key = pathUrl.replace(minIOConfigProperties.getEndpoint() + "/", "");
        int index = key.indexOf(separator);
        String bucket = key.substring(0, index);
        String filePath = key.substring(index + 1);
        // 删除Objects
        RemoveObjectArgs removeObjectArgs = RemoveObjectArgs.builder().bucket(bucket).object(filePath).build();
        try {
            minioClient.removeObject(removeObjectArgs);
        } catch (Exception e) {
            log.error("minio remove file error.  pathUrl:{}", pathUrl);
            e.printStackTrace();
        }
    }


    /**
     * 下载文件
     *
     * @param pathUrl 文件全路径
     * @return 文件流
     * success
     */
    @Override
    public byte[] downLoadFile(String pathUrl) {
        String key = pathUrl.replace(minIOConfigProperties.getEndpoint() + "/", "");
        int index = key.indexOf(separator);
        String bucket = key.substring(0, index);
        String filePath = key.substring(index + 1);
        InputStream inputStream = null;
        try {
            inputStream = minioClient.getObject(GetObjectArgs.builder().bucket(minIOConfigProperties.getBucket()).object(filePath).build());

            String savePath = "/path/to/save/file.txt";
            // 创建保存文件的路径对象

//            Path storageFilePath = Path.of(savePath);
            Path storageFilePath = Paths.get("D:\\data\\logs\\equipment-management-bootstrap-V3.1.3.118.jar");

            // 创建目标文件的父目录（如果不存在）
            Files.createDirectories(storageFilePath.getParent());
            // 将文件保存到指定路径
            Files.copy(inputStream, storageFilePath, StandardCopyOption.REPLACE_EXISTING);
            System.out.println("File downloaded and saved successfully.");


        } catch (Exception e) {
            log.error("minio down file error.  pathUrl:{}", pathUrl);
            e.printStackTrace();
        }

        //字节数组输出流
       /* ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        byte[] buff = new byte[100];
        int rc = 0;
        while (true) {
            try {
                if (!((rc = inputStream.read(buff, 0, 100)) > 0)) {
                    break;
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            byteArrayOutputStream.write(buff, 0, rc);
        }
        return byteArrayOutputStream.toByteArray();*/
        return null;
    }


    /**
     * 查询指定目录下的所有文件名称
     *
     * @param reverse 是否倒叙 默认倒叙
     * @param dirPath
     * @return
     */
//    @Override
    public List<String> listFileName1(String dirPath, Boolean reverse) {
        if (Objects.isNull(reverse)) {
            reverse = true;
        }
        List<String> nameList = new ArrayList<>();
        // 获取指定路径下的对象列表
        Iterable<Result<Item>> objects = minioClient.listObjects(ListObjectsArgs.builder().bucket("pre").prefix(dirPath).recursive(false).build());
//        Iterable<Result<Item>> testObject = minioClient.listObjects(ListObjectsArgs.builder().bucket("pre").recursive(true).build());
//        Iterator<Result<Item>> testiterator = testObject.iterator();
//        while (testiterator.hasNext()) {
//            Result<Item> result = testiterator.next();
//            Item item = null;
//            try {
//                item = result.get();
//            } catch (Exception e) {
//                e.printStackTrace();
//            }
//            System.out.println("888888888888888" + item.objectName());
//
//        }

        // 遍历对象列表并获取文件名称
        Iterator<Result<Item>> iterator = objects.iterator();
        while (iterator.hasNext()) {
            Result<Item> result = iterator.next();
            Item item = null;
            try {
                item = result.get();
            } catch (Exception e) {
                e.printStackTrace();
            }
            ZonedDateTime zonedDateTime = item.lastModified().plusHours(8);
            System.out.println("zonedDateTime:" + zonedDateTime);
            // 定义一个日期时间格式
            String format = "yyyy-MM-dd HH:mm:ss";
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern(format);

            // 将 ZonedDateTime 对象转换为字符串
            String strDate = zonedDateTime.format(formatter);
            System.out.println("转换后的字符串：" + strDate);
            System.out.println(item.objectName());
            System.out.println("isLatest" + item.isLatest());
            nameList.add(strDate + "@" + item.objectName());
        }

        ArrayList<String> finalNameList = new ArrayList<>();
        List<String> collect = new ArrayList<>();
        if (reverse) {
            collect = nameList.stream().sorted(Comparator.reverseOrder()).collect(Collectors.toList());
        } else {
            collect = nameList.stream().sorted(Comparator.naturalOrder()).collect(Collectors.toList());

        }
        for (String s : collect) {
            String[] split = s.split("@");
            if (!StringUtils.isEmpty(split[1])) {
                int i = split[1].lastIndexOf(separator);
                finalNameList.add(split[1].substring(i + 1));
            }

        }
        return finalNameList;
    }


 /*   @Override
    public List<String> listFileName(String dirPath, Boolean reverse) {
        if (Objects.isNull(reverse)) {
            reverse = true;
        }
        List<String> nameList = new ArrayList<>();
        // 获取指定路径下的对象列表
       // Iterable<Result<Item>> objects = minioClient.listObjects(ListObjectsArgs.builder().bucket("pre").prefix(dirPath).recursive(false).build());
        Iterable<Result<Item>> objects = minioClient.listObjects(ListObjectsArgs.builder().bucket("test").prefix(dirPath).recursive(false).build());
        // 遍历对象列表并获取文件名称
        Iterator<Result<Item>> iterator = objects.iterator();
        while (iterator.hasNext()) {
            Result<Item> result = iterator.next();
            Item item = null;
            try {
                item = result.get();
            } catch (Exception e) {
                continue;
            }
            ZonedDateTime zonedDateTime = item.lastModified().plusHours(8);
            // 定义一个日期时间格式
            String format = "yyyy-MM-dd HH:mm:ss";
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern(format);
            // 将 ZonedDateTime 对象转换为字符串
            String strDate = zonedDateTime.format(formatter);
            nameList.add(strDate + "@" + item.objectName());
        }

        ArrayList<String> finalNameList = new ArrayList<>();
        for (String s : nameList) {
            String[] split = s.split("@");
            if (!StringUtils.isEmpty(split[1])) {
                int lastIndexOf = split[1].lastIndexOf(separator);
                finalNameList.add(split[1].substring(lastIndexOf + 1));
            }
        }
        return finalNameList;
    }*/
 @Override
    public List<String> listFileName(String dirPath, Boolean reverse) {
        ArrayList<String> finalNameList = new ArrayList<>();

        String pattern = "yyyy-MM-dd HH:mm:ss";
        List<String> nameList = new ArrayList<>();
        // 获取指定路径下的对象列表
        Iterable<Result<Item>> objects = minioClient.listObjects(ListObjectsArgs.builder().bucket("test").prefix(dirPath).recursive(false).build());
        // 遍历对象列表并获取文件名称
        Iterator<Result<Item>> iterator = objects.iterator();
        while (iterator.hasNext()) {
            Result<Item> result = iterator.next();
            Item item = null;
            try {
                item = result.get();
                if (Objects.nonNull(item)) {
                    ZonedDateTime lastModifiedTime = item.lastModified();
                    if (Objects.nonNull(lastModifiedTime)) {
                        ZonedDateTime zonedDateTime = lastModifiedTime.plusHours(8);
                        // 定义一个日期时间格式
                        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
                        // 将 ZonedDateTime 对象转换为字符串
                        String strDate = zonedDateTime.format(formatter);
                        nameList.add(strDate + "@" + item.objectName());
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
                continue;
            }
        }

        if (!CollectionUtils.isEmpty(nameList)) {
            for (String s : nameList) {
                String[] split = s.split("@");
                if (!StringUtils.isEmpty(split[1])) {
                    int lastIndexOf = split[1].lastIndexOf(separator);
                    finalNameList.add(split[1].substring(lastIndexOf + 1));
                }
            }
        }

        return finalNameList;
    }


}
